import random
from abc import ABC, abstractmethod

import numpy as np
from faker import Faker


class DataGenerator(ABC):
    def __init__(self, db_connector, config):
        """
        初始化数据生成器。
        :param config: 配置信息（从配置文件加载）。
        """
        self.faker = Faker(config.get("faker_locale", "zh_CN"))
        self.sensitive_words = config.get("sensitive_words", [])
        self.data_count_median = config.get("data_count_median", 100)
        self.db_connector = db_connector

    def filter_sensitive_words(self, text, max_attempts=10, regenerate_func=None):
        """
        过滤敏感词，如果包含敏感词则重新生成。
        """
        if regenerate_func is None:
            regenerate_func = lambda: self.faker.sentence(nb_words=5)

        attempts = 0
        while True:
            if not isinstance(text, str):
                text = str(text)

            if not any(word in text for word in self.sensitive_words):
                return text

            if attempts >= max_attempts:
                return "数据生成失败，敏感词超出最大尝试次数"

            text = regenerate_func()
            attempts += 1

    @abstractmethod
    def generate_4_no_text(self, column_info):
        pass

    def generate_data(self, column_info):
        try:

            no_text_v = self.generate_4_no_text(column_info)
            if no_text_v is not None:
                return no_text_v

            return self.filter_sensitive_words(
                eval(column_info['strategy'], {"random": random, "self": self, "faker": self.faker}))
        except Exception as e:
            # 捕获整个逻辑中的所有异常
            raise Exception(f"生成字段 '{column_info['comment']}' 的数据时出错: {e}")

    @abstractmethod
    def insert_row(self, connector, table, row):
        pass

    @staticmethod
    def generate_random_record_count(median_num, std_percent=0.1):
        """
        根据正态分布生成一个记录数值，以中位数为中心。

        :param median_num: 中位数（记录数的核心值）
        :param std_percent: 标准差占中位数的百分比，默认10%
        :return: 一个基于正态分布的可能值
        """
        if median_num <= 0 or std_percent <= 0:
            raise ValueError("中位数和标准差百分比必须为正值")

        # 计算标准差
        std_dev = median_num * std_percent

        # 生成一个正态分布的随机值
        record_count = int(np.random.normal(loc=median_num, scale=std_dev))

        # 保证记录数大于等于0
        return max(10, record_count)

    def generate_test_data_for_table(self, connector, table, strategies):

        success_count = 0  # 成功插入的记录条数
        failure_count = 0  # 失败插入的记录条数
        failure_details = None  # 记录最后一条失败的详细信息

        schema = connector.fetch_table_schema(table)
        row_count = self.generate_random_record_count(self.data_count_median)

        for _ in range(row_count):
            row = {}
            try:
                # 生成每个字段的数据
                for column in schema:
                    column_name = column["COLUMN_NAME"]
                    if not strategies[column_name]['is_gen']:
                        continue
                    try:
                        row[column_name] = self.generate_data(strategies[column_name])
                    except Exception as gen_error:
                        raise ValueError(f"生成字段 '{column_name}' 的数据时出错: {gen_error}")

                c,m = self.insert_row(self.db_connector, table, row)
                if c >= 1:
                    success_count += 1
                else:
                    failure_count += 1
                    failure_details = m
            except Exception as row_error:
                failure_count += 1
                failure_details = {
                    "row": row,
                    "error": str(row_error),
                    "sql": None
                }
        result = {
            "table": table,
            "success_count": success_count,
            "failure_count": failure_count,
            "failure_details": failure_details  # 最后一条失败记录
        }
        return result

    @staticmethod
    def create_generator(db_connector,config):
        db_type = db_connector.get_db_type()
        db_type = db_type.lower()

        if db_type == "mysql":
            from core.generator.mysql_data_generator import MySqlDataGenerator
            return MySqlDataGenerator(db_connector,config)
        else:
            raise ValueError(f"Unsupported database type: {db_type}")
